/*
 * TransiCast / Qt
 * (c) 2012 Joachim Pfeiffer
 * Please refer to http://code.google.com/p/transitacst for more information
 */
#ifndef TRANSITREEMODEL_HPP
#define TRANSITREEMODEL_HPP

#include <QWidget>
#include <QTreeView>
#include <QProgressBar>
#include <QStandardItemModel>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QXmlStreamReader>
#include <QTimer>
#include <QList>
#include <QStandardItem>
#include <QSplashScreen>
#include <QMessageBox>
#include <QMainWindow>

#include <QNetworkSession>

#include <qmobilityglobal.h>
#include <qnetworksession.h>

// QtMobility API headers
// Location
#include <QGeoPositionInfoSource>
#include <QGeoPositionInfo>

#include "utilities.hpp"
#include "busynotify.hpp"
#include "bookmark.hpp"

// QtMobility namespace
QTM_USE_NAMESPACE

class TransiTreeModel : public QStandardItemModel
{
    Q_OBJECT

public:
    explicit TransiTreeModel(QMainWindow *parent = 0, QTreeView *parentView = 0, QApplication *parentApp = 0, BusyNotify *parentHourglass = 0, const QString version = "");

    void loadRoutes(QStandardItem *agency);
    void loadRoute(QStandardItem *route);
    void loadDepartures(QStandardItem *stop, bool clicked);
    void loadDetours(QStandardItem *stop);
    void clearDepartureRequestTimer();
    void clearDepartures();
    QStandardItem *getRequestAgency();
    QStandardItem *getRequestRoute();
    QStandardItem *getSelectedRoute();
    QStandardItem *getRequestStop();
    void startLocation(enum QGeoPositionInfoSource::PositioningMethod method, bool singleShot, QStandardItem *route);
    void stopLocation();
    bool updatingLocation();

    Bookmark *createBookmark();
    void setBookmark(Bookmark *bookmark = NULL);

    // Agency detail columns
    static const int COL_NAME = 0;
    static const int COL_ID = 1;
    static const int COL_DIST_KM = 2;
    static const int COL_ROUTE = 0;
    static const int COL_PRE = 2;
    static const int COL_LAT = 3;
    static const int COL_LON = 4;

signals:
    void displayMsg(const QString& msg);

public slots:
    void killSwitch();
    void loadAgencies();
    void loadRoutes();
    void loadRoute();
    void loadDepartures();

private slots:
    void delayedInit();
    void finishSplash();
    void resetSession();
    void readKillSwitch(QNetworkReply *reply);
    void readAgencies(QNetworkReply *reply);
    void nextAgency();
    void readRoutes(QNetworkReply *reply);
    void nextRoute();
    void readRoute(QNetworkReply *reply);
    void nextStop();
    void readDepartures(QNetworkReply *reply);
    void nextDeparture();
    void readDetours(QNetworkReply *reply);
    void nextDetour();
    void startGpsSingleShot();
    void startNonGpsSingleShot();
    void updateTimeout();
    void positionUpdated(QGeoPositionInfo gpsPos);
    void refreshDistances();
    void bookmarkFollowup();
    void bookmarkFollowupDeparture();

private:
    QMainWindow *modelParent;
    QTreeView *view;
    QApplication *app;
    BusyNotify *hourglass;
    QString parentVersion;

    QSplashScreen *splash;
    QMessageBox *messageBox;
    int detourCount;

    QNetworkAccessManager *killSwitchNetworkAccess;
    QNetworkAccessManager *agencyNetworkXmlAccess;
    QNetworkAccessManager *routeListNetworkXmlAccess;
    QNetworkAccessManager *routeNetworkXmlAccess;
    QNetworkAccessManager *departuresNetworkXmlAccess;
    QNetworkAccessManager *detourNetworkXmlAccess;
    Utilities *utilities;

    qlonglong queryTime;

    void contextSort();
    void processPositionUpdate(QGeoPositionInfo gpsPos);
    void requestKillSwitch();
    void requestAgencies();
    void requestRoutes(QStandardItem *agency);
    void requestRoute(QStandardItem *route);
    void requestDepartures(QStandardItem *stop);
    void requestDetours(QStandardItem *stop);
    void setItemDistance(int row);
    QString calculateAgencyDistance(QStandardItem *topi, QStandardItem *lefti, QStandardItem *bottomi, QStandardItem *righti);
    void manageSiblingVisibility(QStandardItem *item, bool selective);
    void startLocationListening(bool singleShot);

    // RESTful Query elements
    QString transitDataServer;
    QString servletPath;
    QString agencyQuery;
    QString routeListQuery;
    QString routeAgencyQuery;
    QString departureQuery;
    QString detourQuery;
    QString routeQuery;
    QString departureRouteQuery;
    QString detourRouteQuery;
    QString departureAgencyQuery;
    QString relayQuery;
    QString appId;
    QString versionQuery;
    QString personality;
    QStandardItem *slotRequestStop;
    QStandardItem *slotRequestRoute;
    QStandardItem *trackingRoute;
    QStandardItem *slotRequestAgency;
    bool slotClicked;
    QNetworkSession *m_session;

    QXmlStreamReader *agencyReader;
    QXmlStreamReader *routeListReader;
    QXmlStreamReader *routeReader;
    QXmlStreamReader *departureReader;
    QXmlStreamReader *detourReader;
    QNetworkReply *agencyNetworkReply;
    QNetworkReply *routeListNetworkReply;
    QNetworkReply *routeNetworkReply;
    QNetworkReply *departureNetworkReply;
    QNetworkReply *detourNetworkReply;

    QBrush *foreground;

    bool versionChecked;
    bool checkingVersion;

    // Geo location
    QGeoPositionInfoSource *location;
    bool lastKnownPosRead;
    bool isSingleShot;
    QGeoPositionInfo yougeoPosInfo;
    QGeoPositionInfo nullPosInfo;
    QGeoPositionInfo lastPosInfo;
    bool isUpdatingLocation;
    QString closestStopName;
    bool locationTimedOut;

    bool curRequestAgencies;
    QStandardItem *curRequestAgency;
    QStandardItem *curRequestRoute;
    QStandardItem *curRequestStop;
    QStandardItem *curRequestStopDetour;
    QTimer *departureRequestTimer;

    QStandardItem *bookmarkAgency;
    QString bookmarkFollowupRoute;
    QString bookmarkFollowupStop;
    QStandardItem *bookmarkFollowupDepartureRoute;
    QList<QStandardItem *> agencyItem;

    QList<QStandardItem *> agencyTops;
    QList<QStandardItem *> agencyLefts;
    QList<QStandardItem *> agencyBottoms;
    QList<QStandardItem *> agencyRights;
    QList<QStandardItem *> agencyRts;

    int departureQueryCtr;
};

#endif // TRANSITREEMODEL_HPP
